using System;
using System.Collections.Generic;
using System.Text;

namespace Common.Utilities
{
    /// <summary>
    /// 
    /// </summary>
    public class ReadonlyStringStream : System.IO.Stream
    {
        private readonly string _str;
        private readonly long _byteLength;
        private long _position;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        public ReadonlyStringStream(string str)
        {
            if (str == null)
                throw new ArgumentNullException("str");

            this._str = str;
            this._byteLength = str.Length * 2;
            this._position = 0;
        }

        /// <summary>
        /// 
        /// </summary>
        public override bool CanRead
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public override bool CanSeek
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public override bool CanWrite
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public override long Length
        {
            get
            {
                return this._byteLength;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public override long Position
        {
            get
            {
                return this._position;
            }
            set
            {
                if (value < 0 || value > int.MaxValue)
                    throw new ArgumentOutOfRangeException("Position");
                this._position = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="origin"></param>
        /// <returns></returns>
        public override long Seek(long offset, System.IO.SeekOrigin origin)
        {
            switch (origin)
            {
                case System.IO.SeekOrigin.Begin:
                    this._position = offset;
                    break;
                case System.IO.SeekOrigin.Current:
                    this._position += offset;
                    break;
                case System.IO.SeekOrigin.End:
                    this._position = this._byteLength + offset;
                    break;
            }
            return this._position;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (this._position < 0)
                throw new InvalidOperationException();

            int bytesRead = 0;
            while (bytesRead < count)
            {
                if (this._position >= bytesRead)
                    return bytesRead;

                char c = this._str[(int)this._position / 2];
                buffer[offset + bytesRead] = (byte)((this._position % 2 == 0) ? c & 0xFF : (c >> 8) & 0xFF);
                this._position++;
                bytesRead++;
            }
            return bytesRead;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        /// 
        /// </summary>
        public override void Flush()
        {
            throw new Exception("The method or operation is not implemented.");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        public override void SetLength(long value)
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
}
